/**
 * 音频录制模块
 * 负责处理音频录制、暂停、继续和停止功能
 */
class AudioRecorder {
    constructor(options = {}) {
        // 配置选项
        this.sampleRate = options.sampleRate || 16000;
        this.bitDepth = options.bitDepth || 16;
        this.channels = options.channels || 1;
        
        // 录音相关变量
        this.mediaRecorder = null;
        this.audioChunks = [];
        this.isRecording = false;
        this.recordingStartTime = 0;
        this.totalRecordingTime = 0;
        this.pauseTime = 0;
        this.audioStream = null;
        this.audioContext = null;
        this.audioSource = null;
        this.analyser = null;
        this.audioWorkletNode = null;
        this.audioBlob = null;
        this.workletReady = false;
        this.processedChunks = 0; // 记录已处理的块数
        this.chunkStartTime = 0;  // 记录当前块的开始时间
        this.lastChunkEndTime = 0; // 记录上一块的结束时间
        this.isPaused = false;
        
        // 回调函数
        this.onDataAvailable = options.onDataAvailable || null;
        this.onStart = options.onStart || null;
        this.onPause = options.onPause || null;
        this.onResume = options.onResume || null;
        this.onStop = options.onStop || null;
        this.onError = options.onError || null;
        this.onStateChange = options.onStateChange || null;
        this.onNewChunks = options.onNewChunks || null; // 新增回调函数，用于处理新的音频块
        this.onReady = options.onReady || null; // 录音器初始化完成的回调
    }
    
    /**
     * 初始化录音器
     * @returns {Promise<void>}
     */
    async init() {
        try {
            console.log('初始化录音器...');
            
            // 检查浏览器支持
            if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
                throw new Error('此浏览器不支持音频录制功能。请使用更现代的浏览器，如Chrome、Firefox或Edge的最新版本。');
            }
            
            // 创建音频上下文
            const AudioContext = window.AudioContext || window.webkitAudioContext;
            if (!AudioContext) {
                throw new Error('此浏览器不支持AudioContext。请使用更现代的浏览器。');
            }
            
            this.audioContext = new AudioContext();
            console.log(`音频上下文创建成功，采样率: ${this.audioContext.sampleRate}Hz`);
            
            // 获取麦克风访问权限
            console.log('请求麦克风访问权限...');
            try {
                const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
                this.mediaStream = stream;
                console.log('麦克风访问权限已获取');
            } catch (micError) {
                console.error('无法访问麦克风:', micError);
                throw new Error('无法访问麦克风。请确保您的设备有麦克风，并且您已授予网站访问麦克风的权限。');
            }
            
            // 创建音频源节点
            this.audioSource = this.audioContext.createMediaStreamSource(this.mediaStream);
            console.log('音频源节点创建成功');
            
            // 创建分析器节点用于可视化
            this.analyser = this.audioContext.createAnalyser();
            this.analyser.fftSize = 2048;
            this.audioSource.connect(this.analyser);
            
            // 尝试设置 AudioWorklet
            let processorInitialized = false;
            
            try {
                if (this.audioContext.audioWorklet) {
                    console.log('尝试设置 AudioWorklet...');
                    await this.setupAudioWorklet();
                    console.log('AudioWorklet 设置成功');
                    processorInitialized = true;
                } else {
                    console.log('当前浏览器不支持 AudioWorklet，将使用 ScriptProcessor 作为备用');
                    throw new Error('浏览器不支持 AudioWorklet');
                }
            } catch (workletError) {
                console.warn('AudioWorklet 设置失败，错误:', workletError);
                console.log('切换到 ScriptProcessor 作为备用方案');
                
                // 设置 ScriptProcessor 作为备选方案
                try {
                    this.setupScriptProcessor();
                    if (this.scriptProcessorReady) {
                        processorInitialized = true;
                        console.log('ScriptProcessor 设置成功');
                    }
                } catch (scriptError) {
                    console.error('ScriptProcessor 设置失败:', scriptError);
                    throw new Error('音频处理初始化失败: ' + scriptError.message);
                }
            }
            
            if (!processorInitialized) {
                throw new Error('无法初始化录音功能，所有音频处理方法都失败');
            }
            
            console.log('录音器初始化完成');
            
            // 触发就绪回调
            if (this.onReady) {
                setTimeout(() => this.onReady(), 0);
            }
        } catch (error) {
            console.error('录音器初始化失败:', error);
            
            // 释放可能已获取的资源
            this.releaseResources();
            
            // 触发错误回调
            if (this.onError) {
                setTimeout(() => this.onError(error), 0);
            } else {
                // 如果没有错误回调，抛出错误
                throw error;
            }
        }
    }
    
    /**
     * 释放资源
     * 在初始化失败或用户停止录音时调用
     */
    releaseResources() {
        // 关闭音频流
        if (this.mediaStream) {
            this.mediaStream.getTracks().forEach(track => track.stop());
            this.mediaStream = null;
        }
        
        // 断开并清理音频节点
        if (this.audioSource) {
            this.audioSource.disconnect();
            this.audioSource = null;
        }
        
        if (this.audioWorkletNode) {
            this.audioWorkletNode.disconnect();
            this.audioWorkletNode = null;
        }
        
        if (this.scriptProcessor) {
            this.scriptProcessor.disconnect();
            this.scriptProcessor = null;
        }
        
        if (this.analyser) {
            this.analyser.disconnect();
            this.analyser = null;
        }
        
        // 关闭音频上下文
        if (this.audioContext && this.audioContext.state !== 'closed') {
            this.audioContext.close().catch(err => console.error('关闭音频上下文出错:', err));
            this.audioContext = null;
        }
    }
    
    /**
     * 设置 AudioWorklet
     * @returns {Promise<void>}
     */
    async setupAudioWorklet() {
        try {
            console.log('尝试设置AudioWorklet...');
            
            // 检查浏览器是否支持AudioWorklet
            if (!this.audioContext.audioWorklet) {
                throw new Error('此浏览器不支持AudioWorklet');
            }
            
            // 尝试多个可能的路径来加载处理器
            const possiblePaths = [
                '/static/js/recorder-processor.js',
                '/static/js/modules/recorder-processor.js',
                'static/js/recorder-processor.js',
                'static/js/modules/recorder-processor.js'
            ];
            
            let lastError = null;
            
            // 尝试每个可能的路径
            for (const path of possiblePaths) {
                try {
                    console.log(`尝试从路径加载AudioWorklet: ${path}`);
                    await this.audioContext.audioWorklet.addModule(path);
                    console.log(`成功从${path}加载AudioWorklet处理器`);
                    
                    // 如果成功加载，创建AudioWorkletNode
                    this.audioWorkletNode = new AudioWorkletNode(this.audioContext, 'recorder-processor');
                    
                    // 设置消息处理程序
                    this.audioWorkletNode.port.onmessage = (event) => {
                        if (event.data.eventType === 'data') {
                            const audioData = event.data.audioBuffer;
                            
                            // 记录音频数据
                            this.audioChunks.push(audioData);
                            
                            // 如果有数据可用回调，则调用
                            if (this.onDataAvailable) {
                                this.onDataAvailable(audioData);
                            }
                        }
                    };
                    
                    // 连接音频节点
                    this.audioSource.connect(this.audioWorkletNode);
                    this.audioWorkletNode.connect(this.audioContext.destination);
                    
                    console.log('AudioWorklet设置成功');
                    return; // 成功设置后退出
                } catch (error) {
                    console.warn(`从路径${path}加载AudioWorklet失败:`, error);
                    lastError = error;
                }
            }
            
            // 如果所有路径都失败，抛出最后一个错误
            throw new Error(`所有AudioWorklet路径尝试失败: ${lastError?.message || '未知错误'}`);
        } catch (error) {
            console.error('设置AudioWorklet失败:', error);
            throw error; // 重新抛出错误以便在init中处理
        }
    }
    
    /**
     * 设置 ScriptProcessor 作为备用音频处理方案
     */
    setupScriptProcessor() {
        try {
            console.log('设置ScriptProcessor作为备用方案...');
            
            // 创建 ScriptProcessor 节点
            // 注意：ScriptProcessor 已被弃用，但作为备用方案仍然有用
            const bufferSize = 4096;
            this.scriptProcessor = this.audioContext.createScriptProcessor(
                bufferSize, 
                1, // 单声道输入
                1  // 单声道输出
            );
            
            console.log(`ScriptProcessor创建成功，缓冲区大小: ${bufferSize}`);
            
            // 设置音频处理回调
            this.scriptProcessor.onaudioprocess = (audioProcessingEvent) => {
                try {
                    // 只有在录音状态才处理音频数据
                    if (this.isRecording) {
                        // 获取输入数据
                        const inputBuffer = audioProcessingEvent.inputBuffer;
                        const audioData = inputBuffer.getChannelData(0).slice();
                        
                        // 存储音频数据
                        this.audioChunks.push(audioData);
                        
                        // 通知数据可用（确保异步调用在主线程上）
                        if (this.onDataAvailable) {
                            setTimeout(() => {
                                this.onDataAvailable(audioData);
                            }, 0);
                        }
                    }
                } catch (processingError) {
                    console.error('音频处理中发生错误:', processingError);
                }
            };
            
            // 连接音频节点
            this.audioSource.connect(this.scriptProcessor);
            this.scriptProcessor.connect(this.audioContext.destination);
            
            console.log('ScriptProcessor设置完成，音频节点已连接');
            this.scriptProcessorReady = true;
        } catch (error) {
            console.error('设置ScriptProcessor失败:', error);
            
            // 通知用户初始化出错
            if (this.onError) {
                this.onError(new Error('无法初始化录音功能: ' + error.message));
            }
        }
    }
    
    /**
     * 暂停录音
     */
    pause() {
        console.log('录音器暂停方法被调用');
        
        if (!this.isRecording) {
            console.log('录音器未在录音状态，忽略暂停请求');
            return;
        }
        
        try {
            console.log('设置录音器状态为暂停');
            this.isRecording = false;
            this.isPaused = true;
            
            // 通知 AudioWorklet 停止录音
            if (this.audioWorkletNode) {
                try {
                    console.log('通知AudioWorklet停止录音');
                    this.audioWorkletNode.port.postMessage({
                        command: 'setRecording',
                        value: false
                    });
                    
                    // 暂时断开音频处理节点，但不完全清除它，以便恢复时可以重新连接
                    this.audioWorkletNode.disconnect();
                    console.log('AudioWorklet节点断开连接');
                } catch (e) {
                    console.error('断开AudioWorkletNode时发生错误:', e);
                }
            }
            
            // 如果使用的是ScriptProcessor，也需要暂时断开
            if (this.scriptProcessor) {
                try {
                    console.log('断开ScriptProcessor节点');
                    this.scriptProcessor.disconnect();
                } catch (e) {
                    console.error('断开ScriptProcessor时发生错误:', e);
                }
            }
            
            // 记录暂停时的累计时间
            if (this.recordingStartTime > 0) {
                this.totalRecordingTime += (Date.now() - this.recordingStartTime) / 1000;
                console.log('更新累计录音时间:', this.totalRecordingTime, '秒');
            }
            this.pauseTime = Date.now();
            
            // 如果有暂停回调，则调用
            if (this.onPause) {
                // 确保回调在主线程中异步执行
                console.log('触发暂停回调');
                setTimeout(() => this.onPause(), 0);
            }
            
            // 如果有状态变化回调，也调用它
            if (this.onStateChange) {
                console.log('触发状态变化回调: paused');
                setTimeout(() => this.onStateChange('paused'), 0);
            }
            
            console.log('录音暂停成功');
        } catch (error) {
            console.error('暂停录音时发生错误:', error);
            // 即使发生错误，也尝试调用回调
            if (this.onError) {
                setTimeout(() => this.onError(error), 0);
            }
        }
    }
    
    /**
     * 继续录音
     */
    resume() {
        console.log('录音器恢复方法被调用');
        
        if (this.isRecording) {
            console.log('录音器已处于录音状态，忽略恢复请求');
            return;
        }
        
        if (!this.isPaused && !(this.audioWorkletNode || this.scriptProcessor)) {
            console.log('录音器尚未初始化或不在暂停状态，无法恢复');
            return;
        }
        
        try {
            console.log('设置录音器状态为录音中');
            this.isRecording = true;
            this.isPaused = false;
            
            // 更新录音开始时间为当前时间
            this.recordingStartTime = Date.now();
            console.log('更新录音开始时间');
            
            // 重新连接音频处理节点
            if (this.audioWorkletNode && this.audioSource) {
                try {
                    console.log('重新连接AudioWorklet节点');
                    // 重新连接音频源到处理节点
                    this.audioSource.connect(this.audioWorkletNode);
                    // 重新连接处理节点到输出
                    this.audioWorkletNode.connect(this.audioContext.destination);
                    
                    // 通知 AudioWorklet 继续录音
                    console.log('通知AudioWorklet继续录音');
                    this.audioWorkletNode.port.postMessage({
                        command: 'setRecording',
                        value: true
                    });
                } catch (e) {
                    console.error('重新连接AudioWorkletNode时发生错误:', e);
                }
            }
            
            // 如果使用的是ScriptProcessor，也需要重新连接
            if (this.scriptProcessor && this.audioSource) {
                try {
                    console.log('重新连接ScriptProcessor节点');
                    this.audioSource.connect(this.scriptProcessor);
                    this.scriptProcessor.connect(this.audioContext.destination);
                } catch (e) {
                    console.error('重新连接ScriptProcessor时发生错误:', e);
                }
            }
            
            // 如果有继续回调，则调用
            if (this.onResume) {
                // 确保回调在主线程中异步执行
                console.log('触发恢复回调');
                setTimeout(() => this.onResume(), 0);
            }
            
            // 如果有状态变化回调，也调用它
            if (this.onStateChange) {
                console.log('触发状态变化回调: recording');
                setTimeout(() => this.onStateChange('recording'), 0);
            }
            
            console.log('录音恢复成功');
        } catch (error) {
            console.error('恢复录音时发生错误:', error);
            this.isRecording = false;
            // 如果有错误回调，则调用
            if (this.onError) {
                setTimeout(() => this.onError(error), 0);
            }
        }
    }
    
    /**
     * 停止录音
     * @returns {Blob} 录音的WAV文件Blob对象
     */
    stop() {
        if (this.audioWorkletNode || this.scriptProcessor) {
            this.isRecording = false;
            
            // 断开连接
            if (this.audioWorkletNode) {
                this.audioWorkletNode.disconnect();
                this.audioWorkletNode = null;
            }
            
            if (this.scriptProcessor) {
                this.scriptProcessor.disconnect();
                this.scriptProcessor = null;
            }
            
            if (this.audioSource) {
                this.audioSource.disconnect();
            }
            
            // 停止音频流
            if (this.audioStream) {
                this.audioStream.getTracks().forEach(track => track.stop());
            }
            
            // 如果没有音频数据，返回null
            if (this.audioChunks.length === 0) {
                return null;
            }
            
            // 更新总录音时间
            if (this.recordingStartTime > 0) {
                this.totalRecordingTime += (Date.now() - this.recordingStartTime) / 1000;
            }
            
            // 创建WAV文件
            const wavBlob = this.createWavFile(this.audioChunks, this.audioContext.sampleRate, this.bitDepth);
            this.audioBlob = wavBlob;
            
            // 关闭音频上下文
            if (this.audioContext) {
                this.audioContext.close();
                this.audioContext = null;
            }
            
            // 如果有停止回调，则调用
            if (this.onStop) {
                this.onStop(wavBlob);
            }
            
            return wavBlob;
        }
        
        return null;
    }
    
    /**
     * 获取当前录音时间（秒）
     * @returns {number} 录音时间（秒）
     */
    getCurrentTime() {
        // 如果没有在录音且没有开始时间，返回累计时间
        if (!this.isRecording && this.recordingStartTime === 0) {
            return this.totalRecordingTime;
        }
        
        // 返回累计时间加上当前录音段的时间
        const currentSegmentTime = this.isRecording ? (Date.now() - this.recordingStartTime) / 1000 : 0;
        const totalTime = this.totalRecordingTime + currentSegmentTime;
        
        return totalTime;
    }
    
    /**
     * 设置累计录音时间
     * @param {number} time 新的累计录音时间（秒）
     */
    setTotalRecordingTime(time) {
        if (typeof time !== 'number' || isNaN(time)) {
            console.warn(`无效的时间值: ${time}`);
            return;
        }
        
        // 如果当前正在录音，先暂停再继续，以重置当前段的开始时间
        const wasRecording = this.isRecording;
        if (wasRecording) {
            this.pause();
        }
        
        // 设置新的总时间
        this.totalRecordingTime = Math.max(0, time);
        
        // 如果之前在录音，则继续录音
        if (wasRecording) {
            this.resume();
        }
    }
    
    /**
     * 获取分析器节点
     * @returns {AnalyserNode|null} 分析器节点，如果不可用则返回null
     */
    getAnalyser() {
        // 如果分析器未创建或音频上下文已关闭，尝试重新创建
        if (!this.analyser && this.audioContext && this.audioContext.state !== 'closed') {
            try {
                // 创建新的分析器节点
                this.analyser = this.audioContext.createAnalyser();
                this.analyser.fftSize = 2048;
                
                // 如果有音频源，连接到分析器
                if (this.audioSource) {
                    this.audioSource.connect(this.analyser);
                }
                
                console.log('已创建新的音频分析器节点');
            } catch (error) {
                console.error('创建分析器节点失败:', error);
                return null;
            }
        }
        
        return this.analyser;
    }
    
    /**
     * 创建16bit WAV文件
     * @param {Array} audioChunks 音频数据块
     * @param {number} sampleRate 采样率
     * @param {number} bitDepth 位深度
     * @returns {Blob} WAV文件Blob对象
     */
    createWavFile(audioChunks, sampleRate, bitDepth) {
        // 合并所有音频块
        let totalLength = 0;
        for (let i = 0; i < audioChunks.length; i++) {
            totalLength += audioChunks[i].length;
        }
        
        // 创建合并后的Float32Array
        const mergedAudio = new Float32Array(totalLength);
        let offset = 0;
        for (let i = 0; i < audioChunks.length; i++) {
            mergedAudio.set(audioChunks[i], offset);
            offset += audioChunks[i].length;
        }
        
        // 转换为16bit PCM
        const pcmData = new Int16Array(mergedAudio.length);
        for (let i = 0; i < mergedAudio.length; i++) {
            // 将Float32范围(-1,1)转换为Int16范围(-32768,32767)
            const s = Math.max(-1, Math.min(1, mergedAudio[i]));
            pcmData[i] = s < 0 ? Math.round(s * 0x8000) : Math.round(s * 0x7FFF);
        }
        
        // 创建WAV文件头
        const wavHeader = this.createWavHeader(pcmData.length, sampleRate, this.channels, bitDepth);
        
        // 合并头部和数据
        const wavFile = new Blob([wavHeader, pcmData.buffer], { type: 'audio/wav' });
        return wavFile;
    }
    
    /**
     * 从特定的音频块创建WAV文件
     * @param {Array} chunks 音频数据块
     * @param {number} sampleRate 采样率
     * @param {number} bitDepth 位深度
     * @returns {Blob} WAV文件Blob对象
     */
    createWavFileFromChunks(chunks, sampleRate, bitDepth) {
        // 合并指定的音频块
        let totalLength = 0;
        for (let i = 0; i < chunks.length; i++) {
            totalLength += chunks[i].length;
        }
        
        // 创建合并后的Float32Array
        const mergedAudio = new Float32Array(totalLength);
        let offset = 0;
        for (let i = 0; i < chunks.length; i++) {
            mergedAudio.set(chunks[i], offset);
            offset += chunks[i].length;
        }
        
        // 转换为16bit PCM
        const pcmData = new Int16Array(mergedAudio.length);
        for (let i = 0; i < mergedAudio.length; i++) {
            // 将Float32范围(-1,1)转换为Int16范围(-32768,32767)
            const s = Math.max(-1, Math.min(1, mergedAudio[i]));
            pcmData[i] = s < 0 ? Math.round(s * 0x8000) : Math.round(s * 0x7FFF);
        }
        
        // 创建WAV文件头
        const wavHeader = this.createWavHeader(pcmData.length, sampleRate, this.channels, bitDepth);
        
        // 合并头部和数据
        const wavFile = new Blob([wavHeader, pcmData.buffer], { type: 'audio/wav' });
        return wavFile;
    }
    
    /**
     * 创建WAV文件头
     * @param {number} dataLength 数据长度
     * @param {number} sampleRate 采样率
     * @param {number} numChannels 通道数
     * @param {number} bitDepth 位深度
     * @returns {ArrayBuffer} WAV文件头
     */
    createWavHeader(dataLength, sampleRate, numChannels, bitDepth) {
        const bytesPerSample = bitDepth / 8;
        const blockAlign = numChannels * bytesPerSample;
        const byteRate = sampleRate * blockAlign;
        const dataSize = dataLength * bytesPerSample;
        
        const buffer = new ArrayBuffer(44);
        const view = new DataView(buffer);
        
        // RIFF标识
        this.writeString(view, 0, 'RIFF');
        // RIFF块大小
        view.setUint32(4, 36 + dataSize, true);
        // WAVE标识
        this.writeString(view, 8, 'WAVE');
        // fmt子块标识
        this.writeString(view, 12, 'fmt ');
        // fmt子块大小
        view.setUint32(16, 16, true);
        // 音频格式（PCM = 1）
        view.setUint16(20, 1, true);
        // 通道数
        view.setUint16(22, numChannels, true);
        // 采样率
        view.setUint32(24, sampleRate, true);
        // 字节率
        view.setUint32(28, byteRate, true);
        // 块对齐
        view.setUint16(32, blockAlign, true);
        // 每个样本的位数
        view.setUint16(34, bitDepth, true);
        // data子块标识
        this.writeString(view, 36, 'data');
        // data子块大小
        view.setUint32(40, dataSize, true);
        
        return buffer;
    }
    
    /**
     * 重置录音器状态
     */
    reset() {
        // 停止录音（如果正在录音）
        if (this.isRecording) {
            this.stop();
        } else {
            // 如果没有在录音，手动释放资源
            this.releaseResources();
        }
        
        // 重置所有状态变量
        this.audioChunks = [];
        this.isRecording = false;
        this.recordingStartTime = 0;
        this.totalRecordingTime = 0;
        this.pauseTime = 0;
        this.audioBlob = null;
        this.workletReady = false;
        this.scriptProcessorReady = false;
        this.processedChunks = 0;
        this.chunkStartTime = 0;
        this.lastChunkEndTime = 0;
        this.isPaused = false;
    }
    
    /**
     * 在DataView中写入字符串
     * @param {DataView} view DataView对象
     * @param {number} offset 偏移量
     * @param {string} string 要写入的字符串
     */
    writeString(view, offset, string) {
        for (let i = 0; i < string.length; i++) {
            view.setUint8(offset + i, string.charCodeAt(i));
        }
    }
    
    /**
     * 检查是否有保存的录音状态
     * @returns {Promise<boolean>} 是否有保存的状态
     */
    async hasSavedState() {
        // 空方法，始终返回false表示没有保存的状态
        return false;
    }
    
    /**
     * 保存当前录音状态
     * @returns {Promise<boolean>} 是否成功保存
     */
    async saveState() {
        // 空方法，不保存任何数据
        return true;
    }
    
    /**
     * 清除保存的录音状态
     * @returns {Promise<boolean>} 是否成功清除
     */
    async clearSavedState() {
        // 空方法，始终返回成功
        return true;
    }
    
    /**
     * 恢复保存的录音状态
     * @returns {Promise<boolean>} 是否成功恢复
     */
    async restoreState() {
        // 空方法，始终返回失败（因为没有要恢复的内容）
        return false;
    }
    
    /**
     * 获取当前累积的音频块，并生成部分WAV文件
     * 用于流式上传录音数据
     * @returns {Blob|null} 包含当前音频块的WAV文件或null（如果没有新块）
     */
    getAudioChunks() {
        // 检查是否有新的音频块
        if (this.audioChunks.length <= this.processedChunks) {
            return null;
        }
        
        // 获取未处理的音频块
        const newChunks = this.audioChunks.slice(this.processedChunks);
        
        // 更新已处理块的计数
        this.processedChunks = this.audioChunks.length;
        
        // 有新块时，创建临时WAV文件
        if (newChunks.length > 0) {
            // 转换为WAV格式
            const sampleRate = this.audioContext ? this.audioContext.sampleRate : this.sampleRate;
            const wavBlob = this.createWavFileFromChunks(newChunks, sampleRate, this.bitDepth);
            
            // 如果有新块回调，通知新块已可用
            if (this.onNewChunks) {
                this.onNewChunks(wavBlob, this.processedChunks, this.audioChunks.length);
            }
            
            return wavBlob;
        }
        
        return null;
    }
    
    /**
     * 标记并获取当前词的音频数据
     * 在用户点击"下一词"时调用
     * @param {Object} wordInfo 当前词的信息对象
     * @returns {Blob|null} 当前词对应的音频数据块，如果没有则返回null
     */
    markWordAndGetAudio(wordInfo) {
        if (!this.isRecording || !this.audioContext) {
            return null;
        }
        
        // 获取当前时间作为当前词的结束时间
        const currentTime = this.getCurrentTime();
        const wordEndTime = currentTime;
        
        // 如果有上一个块，则使用其结束时间作为开始时间；否则使用0
        const wordStartTime = this.lastChunkEndTime || 0;
        
        // 更新下一个块的开始时间
        this.lastChunkEndTime = wordEndTime;
        
        // 如果没有新的音频块，返回null
        if (this.audioChunks.length <= this.processedChunks) {
            return null;
        }
        
        // 获取未处理的音频块
        const newChunks = this.audioChunks.slice(this.processedChunks);
        
        // 更新已处理块的计数
        this.processedChunks = this.audioChunks.length;
        
        // 有新块时，创建临时WAV文件
        if (newChunks.length > 0) {
            // 转换为WAV格式
            const sampleRate = this.audioContext ? this.audioContext.sampleRate : this.sampleRate;
            const wavBlob = this.createWavFileFromChunks(newChunks, sampleRate, this.bitDepth);
            
            // 如果传入了词信息，添加时间信息
            if (wordInfo) {
                wordInfo.startTime = wordStartTime;
                wordInfo.endTime = wordEndTime;
                wordInfo.duration = wordEndTime - wordStartTime;
            }
            
            // 如果有新块回调，通知新块已可用
            if (this.onNewChunks) {
                this.onNewChunks(wavBlob, wordInfo, this.audioChunks.length);
            }
            
            return wavBlob;
        }
        
        return null;
    }
    
    /**
     * 开始录音
     * @returns {Promise<boolean>} 是否成功开始录音
     */
    async start() {
        try {
            // 如果已经在录音，先停止
            if (this.isRecording) {
                this.stop();
            }
            
            // 如果没有初始化或上下文已关闭，重新初始化
            if (!this.audioContext || this.audioContext.state === 'closed') {
                await this.init();
            }
            
            // 设置录音状态
            this.isRecording = true;
            this.isPaused = false;
            this.recordingStartTime = Date.now();
            this.audioChunks = [];
            this.processedChunks = 0;
            this.lastChunkEndTime = 0;
            
            // 如果有开始回调，调用它
            if (this.onStart) {
                setTimeout(() => this.onStart(), 0);
            }
            
            // 如果有状态变化回调，调用它
            if (this.onStateChange) {
                setTimeout(() => this.onStateChange('recording'), 0);
            }
            
            return true;
        } catch (error) {
            console.error('开始录音失败:', error);
            
            // 如果有错误回调，调用它
            if (this.onError) {
                setTimeout(() => this.onError(error), 0);
            }
            
            return false;
        }
    }
}

// 导出AudioRecorder类
window.AudioRecorder = AudioRecorder; 